package cn.jly.akka.actors_communicate

import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
import com.typesafe.config.{Config, ConfigFactory}

import scala.io.StdIn

object ClientActorApp extends App {
  val (clientHost, clientPort, serverHost, serverPort, serverActorSystemName, serverActorRefName) =
    ("127.0.0.1", 8888, "127.0.0.1", 9999, "serverActorSystem", "serverActorRef")

  println((clientHost, clientPort, serverHost, serverPort, serverActorSystemName, serverActorRefName))

  // 客户端actorSystem的config
  private val config: Config = ConfigFactory.parseString(
    s"""
       |akka.actor.provider="akka.remote.RemoteActorRefProvider"
       |akka.remote.netty.tcp.hostname=$clientHost
       |akka.remote.netty.tcp.port=$clientPort
      """.stripMargin)

  // 客户端clientActor的 actorSystem
  private val clientActorSystem: ActorSystem = ActorSystem("clientActorSystem", config)
  // 客户端clientActor的 clientActorRef
  private val clientActorRef: ActorRef =
    clientActorSystem.actorOf(Props(new ClientActor(serverHost, serverPort, serverActorSystemName, serverActorRefName)),
      "clientActorRef")

  // 运行
  clientActorRef ! "start"

  import scala.util.control.Breaks._
  // 发消息通信
  breakable {
    while (true) {
      println("请输入想要咨询的问题：")
      // 接受用户输入
      val input: String = StdIn.readLine
      clientActorRef ! input

      // 程序终止
      if ("exit".equals(input))
        break()
    }
  }
}

// client actor
class ClientActor(serverHost: String, serverPort: Int, serverActorSystemName: String, serverActorRefName: String) extends Actor {
  // 定义一个serverActorRef
  var serverActorRef: ActorSelection = _

  // 初始化工作，在actor执行之前执行
  override def preStart(): Unit = {
    println("clientActor preStart() 执行了..")

    // 初始化serverActorRef
    serverActorRef =
      context.actorSelection(s"akka.tcp://${serverActorSystemName}@${serverHost}:${serverPort}/user/${serverActorRefName}")

    println(serverActorRef)
  }

  override def receive: Receive = {
    case "start" => println("收到start执行，客户端clientActor开始启动")
    // 处理退出客户端指令
    case "exit" => {
      println("收到exit执行，客户端clientActor服务停止")
      // 停止客户端clientActor
      context.stop(self)
      // 停止客户端clientActorSystem
      context.system.terminate()
    }
    // 给服务端发信息
    case msg: String => serverActorRef ! ClientMessage(msg)
    // 处理来自服务端的回复
    case ServerMessage(msg) => println(s"收到来自服务端serverActor的回复，回复内容为：$msg")
  }

  override def postStop(): Unit = super.postStop()
}